package com.region.http.client.core;

import com.region.common.adapter.logging.LoggerAdapter;
import com.region.common.adapter.logging.LoggerAdapterFactory;
import com.region.http.client.model.RequestMeta.RequestMetaBuilder;

import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * @author 26225
 * @date 2024/8/31 15:34
 * @description
 */
public class MetaChain {

    private List<MetaResolver> resolvers = new LinkedList<>();

    private Iterator<MetaResolver> iterator;

    private final LoggerAdapter loggerAdapter = LoggerAdapterFactory.getLogger(getClass());

    public MetaChain() {
        super();
        resolvers.add(new RequestMetaResolver());
        resolvers.add(new AsynchronousMetaResolver());
        resolvers.add(new LocalConfigurerMetaResolver());
        resolvers.add(new ConstMetaResolver());
    }

    public void executeChain(RequestMetaBuilder builder, Annotation annotation) {
        if (iterator == null) {
            iterator = resolvers.iterator();
            if (iterator.hasNext()) {
                iterator.next().doResolver(builder, annotation, this);
            }
        } else {
            loggerAdapter.warn("The meta chain was running.");
        }
        reset();
    }

    public void addResolver(MetaResolver metaResolver) {
        resolvers.add(metaResolver);
        resolvers.sort(Comparator.comparingInt(MetaResolver::getPriority));
    }

    public void doResolver(RequestMetaBuilder builder, Annotation annotation) {
        if (iterator.hasNext()) {
            MetaResolver resolver = iterator.next();
            resolver.doResolver(builder, annotation, this);
        } else {
            if (loggerAdapter.isDebugEnabled()) {
                loggerAdapter.debug("The current " + builder + " chain execution is completed.");
            }
        }
    }

    private void reset() {
        if (loggerAdapter.isDebugEnabled()) {
            loggerAdapter.debug("Forthcoming reset.");
        }
        this.iterator = null;
    }

}
